#include <iostream>
#include <vector>
#include "checker.h"
#include "dist_calculator.h"
#undef assert
#include "assert.h"

using namespace std;

bool SymmetricChecker::check(const ProcessState& state, size_t symmetric)
{
    for(size_t i = 0; i < state.numVertecies; ++i) {
        //Delete from symmetric elements, which equal to 1
        size_t curElem = elements[state.vertecies[i]];
        size_t currentSymmetric = (symmetric & (~curElem));
        //Shift to n, for changing bits, which shows 2
        currentSymmetric <<= n;
        vertecies_[i] = (currentSymmetric ^ curElem);
        vertecies_[i] = elements.findVertexIndex(vertecies_[i]);
    }
    std::sort(vertecies_, vertecies_ + state.numVertecies);
    return !std::lexicographical_compare(vertecies_, vertecies_ + state.numVertecies,
            state.vertecies, state.vertecies + state.numVertecies);
}

bool FinalSymmetricChecker::check(const ProcessState& state)
{
    assert(state.numVertecies > 0, "state.numVertecies > 0");
    if ((elements[state.vertecies[0]] >> n) != 0) {
        incrementFalseNumber();
        return false;
    }
    for(size_t v = 1; v < state.numVertecies; ++v) {
        if (!helperChecker_.check(state, elements[state.vertecies[v]] >> n)) {
            incrementFalseNumber();
            return false;
        }
    }
    return true;
}

bool OnlineSymmetricChecker::check(const ProcessState& state)
{
    assert(state.numVertecies > 0, "state.numVertecies > 0");
    if ((elements[state.vertecies[0]] >> n) != 0) {
        incrementFalseNumber();
        return false;
    }
    size_t lastv = state.vertecies[state.numVertecies - 1];
    if (!helperChecker_.check(state, (elements[lastv] >> n))) {
        incrementFalseNumber();
        return false;
    }
    return true;
}

bool CoordNChecker::check(const size_t* const a, size_t k, size_t l, size_t r)
{
    if (l == r || k == 0) {
        return true;
    }
    unsigned char curbit, lastbit = 2;
    size_t v = elements[a[0]];
    for(size_t i = l; i < r; ++i) {
        curbit = bit(v, i);
        if (curbit > lastbit) {
            return false;
        }
        if (curbit < lastbit) {
            bool res = check(a + 1, k - 1, l, i);
            if (!res) {
                return false;
            }
            l = i;
        }
        lastbit = curbit;
    }
    return check(a + 1, k - 1, l, r);
}

OnlineSymmetricCoordChecker::OnlineSymmetricCoordChecker()
    :checker_(new CoordNChecker())
{
}

bool OnlineSymmetricCoordChecker::check(const ProcessState& state)
{
    if (state.numVertecies <= MAX_PROCESSED || true) {
        if (!checker_->check(state.vertecies, state.numVertecies, 0, n)) {
            incrementFalseNumber();
            return false;
        }
    }
    return true;
}

bool FinalDimensionChecker::check(const ProcessState& state)
{
    return true;
    size_t ors = 0;
    for(size_t i = 0; i < state.numVertecies; ++i) {
        ors |= state.vertecies[i];
    }
    if (ors + 1 != SIZE_VMSK) {
        incrementFalseNumber();
        return false;
    }
    return true;
}

bool OnlineDimensionChecker::check(const ProcessState& state)
{
    return true;
/*    if (state.numVerteciesWithLargestBit > 0)
    {
        return true;
    } else {
        incrementFalseNumber();
        return false;
    }*/
}

bool FinalBiparateChecker::check(const ProcessState& state)
{
    if (!biparate(state.subGraph))
    {
        return true;
    } else {
        incrementFalseNumber();
        return false;
    }
}

bool FinalNaiveColoringChecker::check(const ProcessState& state)
{
    if (naiveColoring(state.subGraph) > n + 1)
    {
        return true;
    } else {
        incrementFalseNumber();
        return false;
    }
}

bool FinalCorrectColoringChecker::check(const ProcessState& state)
{
    if (!correctColoring(state.subGraph))
    {
        return true;
    } else {
        incrementFalseNumber();
        return false;
    }
}

bool OnlineMaxDegreeChecker::check(const ProcessState& state)
{
    bool res = state.potentialDegree.degreeSet.maxValue() > maxDegree_;
    if (!res) {
        incrementFalseNumber();
    }
    return res;
}

bool OnlineColoringChecker::check(const ProcessState& state)
{
    bool res = state.colorInfo.maxColor.maxValue() > maxColor_;
    if (!res) {
/*        size_t mc = 0;
        for(size_t v = 0; v < state.newGraph->numVertecies(); ++v) {
            if (state.getted[v] == 0) {
                continue;
            }
            mc = std::max(mc, state.colorInfo.color[v]);
            const vector<size_t>& inc = state.newGraph->incendents(v);
            for(size_t j = 0; j < inc.size(); ++j) {
                size_t u = inc[j];
                if (state.getted[u] == 0) {
                    continue;
                }
                assert((state.colorInfo.color[u] != state.colorInfo.color[v]));
            }
        }
        assert(mc <= maxColor_);*/
        incrementFalseNumber();
    }
    return res;
}
